package com.xdl.modules.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xdl.common.constants.CommonConstants;
import com.xdl.common.constants.FillRuleConstant;
import com.xdl.common.utils.SnowflakeIdUtil;
import com.xdl.common.utils.StringUtils;
import com.xdl.modules.system.entity.*;
import com.xdl.modules.system.mapper.SysDepartMapper;
import com.xdl.modules.system.model.DepartIdModel;
import com.xdl.modules.system.model.SysDepartTreeModel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xdl.modules.system.service.*;
import com.xdl.modules.utils.FindsDepartsChildrenUtil;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 组织机构表 服务实现类
 * </p>
 *
 * @author iron guo
 * @since 2022-03-05
 */
@Service
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements SysDepartService {

    @Autowired
    private FillRuleService fillRuleService;

    @Autowired
    private SysDepartRoleUserService departRoleUserService;

    @Autowired
    private SysDepartRolePermissionService departRolePermissionService;

    @Autowired
    private SysDepartRoleService departRoleService;

    @Autowired
    private SysUserDepartService userDepartService;

    @Autowired
    private SysDepartPermissionService departPermissionService;

    @Override
    public List<SysDepart> queryUserDeparts(String id) {
        return baseMapper.queryUserDeparts(id);
    }

    @Override
    public List<SysDepartTreeModel> queryTreeList(String ids) {
        List<SysDepartTreeModel> modelList;
        if (StringUtils.isNotEmpty(ids)) {
            modelList = getSysDepartTree(ids);
        } else {
            modelList = buildTree();
        }
        return modelList;
    }

    @Override
    public List<DepartIdModel> queryDepartIdTreeList() {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<DepartIdModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToDepartIdTreeList(list);
        return listResult;
    }

    @Override
    @Transactional
    public boolean saveDepartData(SysDepart sysDepart, String username) {
        if (sysDepart != null && username != null) {
            if (sysDepart.getParentId() == null) {
                sysDepart.setParentId("");
            }
            sysDepart.setId(String.valueOf(SnowflakeIdUtil.nextId()));
            // 先判断该对象有无父级ID,有则意味着不是最高级,否则意味着是最高级
            // 获取父级ID
            String parentId = sysDepart.getParentId();
            //部门编码规则生成器做成公用配置
            JSONObject formData = new JSONObject();
            formData.put("parentId", parentId);
            String[] codeArray = (String[]) fillRuleService.executeRule(FillRuleConstant.DEPART, formData);
            sysDepart.setOrgCode(codeArray[0]);
            String orgType = codeArray[1];
            sysDepart.setOrgType(String.valueOf(orgType));
            sysDepart.setCreateTime(LocalDateTime.now());
            sysDepart.setDelFlag(CommonConstants.DEL_FLAG_0.toString());
            this.save(sysDepart);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchWithChildren(List<String> ids) {
        List<String> idList = new ArrayList<String>();
        for (String id : ids) {
            idList.add(id);
            this.checkChildrenExists(id, idList);
        }
        this.removeByIds(idList);
        //根据部门id获取部门角色id
        List<String> roleIdList = new ArrayList<>();
        LambdaQueryWrapper<SysDepartRole> query = new LambdaQueryWrapper<>();
        query.select(SysDepartRole::getId).in(SysDepartRole::getDepartId, idList);
        List<SysDepartRole> depRoleList = departRoleService.list(query);
        for (SysDepartRole deptRole : depRoleList) {
            roleIdList.add(deptRole.getId());
        }
        //根据部门id删除用户与部门关系
        userDepartService.remove(new LambdaQueryWrapper<SysUserDepart>().in(SysUserDepart::getDepId, idList));
        //根据部门id删除部门授权
        departPermissionService.remove(new LambdaQueryWrapper<SysDepartPermission>().in(SysDepartPermission::getDepartId, idList));
        //根据部门id删除部门角色
        departRoleService.remove(new LambdaQueryWrapper<SysDepartRole>().in(SysDepartRole::getDepartId, idList));
        if (roleIdList != null && roleIdList.size() > 0) {
            //根据角色id删除部门角色授权
            departRolePermissionService.remove(new LambdaQueryWrapper<SysDepartRolePermission>().in(SysDepartRolePermission::getRoleId, roleIdList));
            //根据角色id删除部门角色用户信息
            departRoleUserService.remove(new LambdaQueryWrapper<SysDepartRoleUser>().in(SysDepartRoleUser::getDroleId, roleIdList));
        }
    }

    @Override
    public List<SysDepartTreeModel> queryMyDeptTreeList(String departIds) {
        //根据部门id获取所负责部门
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        String[] codeArr = this.getMyDeptParentOrgCode(departIds);
        for (int i = 0; i < codeArr.length; i++) {
            query.or().likeRight(SysDepart::getOrgCode, codeArr[i]);
        }
        query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        query.orderByAsc(SysDepart::getDepartOrder);
        //将父节点ParentId设为null
        List<SysDepart> listDepts = this.list(query);
        for (int i = 0; i < codeArr.length; i++) {
            for (SysDepart dept : listDepts) {
                if (dept.getOrgCode().equals(codeArr[i])) {
                    dept.setParentId(null);
                }
            }
        }
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(listDepts);
        return listResult;
    }

    @Override
    public List<String> getMySubDepIdsByDepId(String departIds) {
        //根据部门id获取所负责部门
        String[] codeArr = this.getMyDeptParentOrgCode(departIds);
        if (codeArr == null || codeArr.length == 0) {
            return null;
        }
        return this.baseMapper.getSubDepIdsByOrgCodes(codeArr);
    }

    @Override
    public List<String> getSubDepIdsByDepId(String depId) {
        return this.baseMapper.getSubDepIdsByDepId(depId);
    }

    /**
     * <p>
     * 根据关键字搜索相关的部门数据
     * </p>
     */
    @Override
    public List<SysDepartTreeModel> searchByKeyWord(String keyWord, String myDeptSearch, String departIds) {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        List<SysDepartTreeModel> newList = new ArrayList<>();
        //myDeptSearch不为空时为我的部门搜索，只搜索所负责部门
        if (!StringUtil.isNullOrEmpty(myDeptSearch)) {
            //departIds 为空普通用户或没有管理部门
            if (StringUtil.isNullOrEmpty(departIds)) {
                return newList;
            }
            //根据部门id获取所负责部门
            String[] codeArr = this.getMyDeptParentOrgCode(departIds);
            //当用户属于两个部门的时候，且这两个部门没有上下级关系，我的部门-部门名称查询条件模糊搜索失效！
            if (codeArr != null && codeArr.length > 0) {
//                query.nested(i -> {
//                    for (String s : codeArr) {
//                        i.or().likeRight(SysDepart::getOrgCode, s);
//                    }
//                });
                for (String s : codeArr) {
                    query.nested(i -> i.or().likeRight(SysDepart::getOrgCode, s));
                }
            }
            //当用户属于两个部门的时候，且这两个部门没有上下级关系，我的部门-部门名称查询条件模糊搜索失效！
            query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        }
        query.like(SysDepart::getDepartName, keyWord);
        //组织机构搜索回显优化
        SysDepartTreeModel model = new SysDepartTreeModel();
        List<SysDepart> departList = this.list(query);
        if (departList.size() > 0) {
            for (SysDepart depart : departList) {
                model = new SysDepartTreeModel(depart);
                model.setChildren(null);
                //组织机构搜索功回显优化
                newList.add(model);
            }
            return newList;
        }
        return null;
    }

    /**
     * updateDepartDataById 对应 edit 根据部门主键来更新对应的部门数据
     */
    @Override
    @Transactional
    public boolean updateDepartDataById(SysDepart sysDepart, String username) {
        if (sysDepart != null && username != null) {
            sysDepart.setUpdateTime(LocalDateTime.now());
            sysDepart.setUpdateBy(username);
            this.updateById(sysDepart);
            return true;
        } else {
            return false;
        }

    }

    /**
     * 根据用户所负责部门ids获取父级部门编码
     *
     * @param departIds
     * @return
     */
    private String[] getMyDeptParentOrgCode(String departIds) {
        //根据部门id查询所负责部门
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        query.in(SysDepart::getId, Arrays.asList(departIds.split(",")));
        query.orderByAsc(SysDepart::getOrgCode);
        List<SysDepart> list = this.list(query);
        //查找根部门
        if (list == null || list.size() == 0) {
            return null;
        }
        String orgCode = this.getMyDeptParentNode(list);
        String[] codeArr = orgCode.split(",");
        return codeArr;
    }


    /**
     * 获取负责部门父节点
     *
     * @param list
     * @return
     */
    private String getMyDeptParentNode(List<SysDepart> list) {
        Map<String, String> map = new HashMap<>();
        //1.先将同一公司归类
        for (SysDepart dept : list) {
            String code = dept.getOrgCode().substring(0, 3);
            if (map.containsKey(code)) {
                String mapCode = map.get(code) + "," + dept.getOrgCode();
                map.put(code, mapCode);
            } else {
                map.put(code, dept.getOrgCode());
            }
        }
        StringBuffer parentOrgCode = new StringBuffer();
        //2.获取同一公司的根节点
        for (String str : map.values()) {
            String[] arrStr = str.split(",");
            parentOrgCode.append(",").append(this.getMinLengthNode(arrStr));
        }
        return parentOrgCode.substring(1);
    }

    /**
     * 获取同一公司中部门编码长度最小的部门
     *
     * @param str
     * @return
     */
    private String getMinLengthNode(String[] str) {
        int min = str[0].length();
        String orgCode = str[0];
        for (int i = 1; i < str.length; i++) {
            if (str[i].length() <= min) {
                min = str[i].length();
                orgCode = orgCode + "," + str[i];
            }
        }
        return orgCode;
    }

    /**
     * delete 方法调用
     *
     * @param id
     * @param idList
     */
    private void checkChildrenExists(String id, List<String> idList) {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getParentId, id);
        List<SysDepart> departList = this.list(query);
        if (departList != null && departList.size() > 0) {
            for (SysDepart depart : departList) {
                idList.add(depart.getId());
                this.checkChildrenExists(depart.getId(), idList);
            }
        }
    }

    private List<SysDepartTreeModel> getSysDepartTree(String ids) {
        List<SysDepartTreeModel> listResult = new ArrayList<>();
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        if (StringUtils.isNotEmpty(ids)) {
            query.in(true, SysDepart::getId, ids.split(","));
        }
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        for (SysDepart depart : list) {
            listResult.add(new SysDepartTreeModel(depart));
        }
        return listResult;
    }


    private List<SysDepartTreeModel> buildTree() {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstants.DEL_FLAG_0.toString());
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
        return listResult;
    }


}
